#ifndef RESSOURCE_MANAGER_H
#define RESSOURCE_MANAGER_H

#include "stdafx.h"
#include "Singleton.h"
#include "DispositifD3D.h"

namespace PM3D
{
    template <class T>
    class RessourceManager : public Singleton < RessourceManager < T > >
    {
    public:
        typedef T ressourceType;
        typedef T* ressourcePtr;

        RessourceManager();
        ~RessourceManager();
        void cleanup();

        // pour les textures
        ressourcePtr getNewRessource(const std::wstring& filename, 
            Dispositif* Device, DWORD cleCouleur);

        // pour les shaders et les meshs
        ressourcePtr getNewRessource(const std::wstring& filename, 
        Dispositif* Device);

        // pour le son
        ressourcePtr getNewRessource(const std::string& filename);
    private:
        std::map<std::wstring, ressourcePtr> mapRessource_;

        ressourcePtr getRessource(const std::wstring& filename);
    };

    template <class T>
    RessourceManager<T>::RessourceManager()
    {
    }

    template <class T>
    RessourceManager<T>::~RessourceManager()
    {
        cleanup();
    }

    template <class T>
    typename RessourceManager<T>::ressourcePtr 
    RessourceManager<T>::getNewRessource(const std::wstring& filename, 
            Dispositif* Device, DWORD cleCouleur)
    {
        ressourcePtr ressource = getRessource(filename);

        if (!ressource)
        {
            ressource = new T(filename, Device, cleCouleur);
            mapRessource_[filename] = ressource;
        }

        return ressource;
    }

    template <class T>
    typename RessourceManager<T>::ressourcePtr 
        RessourceManager<T>::getNewRessource(
        const std::wstring& filename, Dispositif* Device)
    {
        ressourcePtr ressource = getRessource(filename);

        if (!ressource)
        {
            ressource = new T(filename, Device);
            mapRessource_[filename] = ressource;
        }

        return ressource;
    }

    template <class T>
    typename RessourceManager<T>::ressourcePtr 
        RessourceManager<T>::getNewRessource(
        const std::string& filename)
    {
        const int MAX_FILENAME = 256;

        wchar_t temp[MAX_FILENAME];
        std::mbstowcs(temp, filename.c_str(), MAX_FILENAME - 1);
        std::wstring wideFilename(temp);

        ressourcePtr ressource = getRessource(wideFilename);

        if (!ressource)
        {
            ressource = new T(filename);
            mapRessource_[wideFilename] = ressource;
        }

        return ressource;
    }

    template <class T>
    typename RessourceManager<T>::ressourcePtr 
        RessourceManager<T>::getRessource(const std::wstring& filename)
    {
        auto itt = mapRessource_.find(filename);
        return (itt != mapRessource_.end())? (*itt).second : nullptr;
    }

    template <class T>
    void RessourceManager<T>::cleanup()
    {
        std::for_each(mapRessource_.begin(), mapRessource_.end(),
            [](std::pair<std::wstring, ressourcePtr> ressource)
        {
            delete ressource.second;
            ressource.second = nullptr;
        });
    }

}   // namespace PM3D

#endif   //   RESSOURCE_MANAGER_H
